<& /Elements/Header, Title => "NSA" &>
<& /Elements/Tabs,
    current_toptab => "NSA/index.html",
    Title => "Network Service Assessment" &>

% if ($nmap) {
<& /Elements/TitleBoxStart, contentbg => "#cccccc", title => "Database Exceptions" &>
% while (my $type = $types->Next) {
%     next if ($type->Name =~ /application/i);
  <h3>Device Type: <%$type->Name%></h3>
  <table border='1'>
  <tr>
    <th></th>
% if ($Tickets) {
    <th>Ticket</th>
% }
    <th>IP Addr</th>
    <th>Database Info.</th>
    <th>Category</th>
  </tr>
<%perl>
   # Database Exceptions
   foreach my $excep (keys %$db_exceptions) {
       next unless $db_exceptions->{$excep}{object}->Type == $type->id;
       my $object = $db_exceptions->{$excep}{object};
       my $asset_uri = RT::URI->new($RT::SystemUser);
       my $ticket_uri = RT::URI->new($RT::SystemUser);
       $asset_uri->FromObject($object);
       my ($rv, $msg, $ticket);
       if ($Tickets && ((defined $TicketLimit && $counter < $TicketLimit) || !defined $TicketLimit )) {
           $ticket = RT::Ticket->new($session{CurrentUser});
           ($rv, $msg) = $ticket->Create(Queue => $Queue, Subject => "IP $excep not found during security scan",
                                         MIMEObj => MakeMIMEEntity(Body => "The IP address $excep associated with " . $object->Name . 
                                                                  " was not detected during a routine security scan of the network. \nPlease" .
                                                                  " review the database entry for that system and update it if necessary. $bonus_info"),
                                         RefersTo => [$asset_uri->URI],
                                         AdminCc => [ split(', ', $object->AdminGroup->MemberEmailAddressesAsString), split(', ', $object->TypeObj->Admin->MemberEmailAddressesAsString) ],
                                         "CustomField-".$nsa->id    => $ARGS{$nsa->id ."-Values"},
                                         "CustomField-".$network->id    => $ARGS{$network->id ."-Values"},
                                         "CustomField-".$risk->id   => "Low",
                                         "CustomField-".$status->id => "Device not up",
                                         "CustomField-".$guess->id => "N/A",
                                         "CustomField-".$ip->id => $excep,
                                         Requestor => $session{'CurrentUser'}->UserObj->EmailAddress);
           unless ($rv) { $m->comp('/Elements/Error', Why => $msg); $m->abort; }
           $ticket_uri->FromObject($ticket);
       }
</%perl>
  <tr>
    <td><% ++$counter %></td>
% if ($Tickets) {
    <td><% $rv ? "<a href='".$ticket_uri->Resolver->HREF. "'>$rv</a>" : $msg |n %></td>
% }
    <td><%$excep%></td>
    <td><a href="/AssetTracker/Asset/Display.html?id=<%$object->id%>"><%$object->Name%></a></td>
    <td><%$db_exceptions->{$excep}{category}%></td>
  </tr>
%   }
  </table>
% }
<& /Elements/TitleBoxEnd, contentbg => "#cccccc" &>

<& /Elements/TitleBoxStart, contentbg => "#cccccc", title => "Non-Database Exceptions" &>
  <h3>Device Type: Unknown</h3>
  <table border='1'>
  <tr>
    <th></th>
% if ($Tickets) {
    <th>Ticket</th>
% }
    <th>IP Addr</th>
    <th>Scan Info.</th>
    <th>OS Guess</th>
  </tr>
<%perl>
   # Non-Database Exceptions
   foreach my $excep (keys %$non_db_exceptions) {
       my $ticket_uri = RT::URI->new($RT::SystemUser);
       my ($rv, $msg, $ticket);
       if ($Tickets && ((defined $TicketLimit && $counter < $TicketLimit) || !defined $TicketLimit )) {
           $ticket = RT::Ticket->new($session{CurrentUser});
           ($rv, $msg) = $ticket->Create(Queue => $Queue, Subject => "IP $excep acting as server but not found in DB during security scan",
                                         MIMEObj => MakeMIMEEntity(Body => "The system $excep is acting as a server but is not " .
                                                                   "registered in the server database. \nPlease review this system " .
                                                                   "and take the proper corrective action. \nThe system is listening on " .
                                                                   "the following TCP ports: " . join(', ', @{$struct->{$excep}{tcp}{open}})
                                                                   . $bonus_info 
                                                                     ),
                                         "CustomField-".$nsa->id    => $ARGS{$nsa->id ."-Values"},
                                         "CustomField-".$network->id    => $ARGS{$network->id ."-Values"},
                                         "CustomField-".$guess->id => $non_db_exceptions->{$excep}{osguess},
                                         "CustomField-".$ip->id => $excep,
                                         "CustomField-".$ports->id => [ NSA::offending_ports( @{$struct->{$excep}{tcp}{open}} ) ],
                                         Requestor => $session{'CurrentUser'}->UserObj->EmailAddress);
           unless ($rv) { $m->comp('/Elements/Error', Why => $msg); $m->abort; }
           $ticket_uri->FromObject($ticket);
       }
</%perl>
  <tr>
    <td><% ++$counter %></td>
% if ($Tickets) {
    <td><% $rv ? "<a href='".$ticket_uri->Resolver->HREF. "'>$rv</a>" : $msg |n %></td>
% }
    <td><%$excep%></td>
    <td><% join(', ', @{$struct->{$excep}{tcp}{open}}) %></td>
    <td><%$non_db_exceptions->{$excep}{osguess}%></td>
  </tr>
%   }
  </table>
<& /Elements/TitleBoxEnd, contentbg => "#cccccc" &>

% }

<FORM METHOD="post" ENCTYPE="multipart/form-data">
<& /Elements/TitleBoxStart, contentbg => "#cccccc", title => loc("Process nMap scan") &>
<table>
%#<tr><td>Scan Date: </td><td><INPUT NAME="Date" SIZE="10" VALUE="<%$ARGS{'Date'}%>"></td>
<tr><td>Description: </td><td><INPUT NAME="Description" SIZE="30" VALUE="<%$ARGS{'Description'}%>"></td>
<tr><td>nmap XML file: </td><td><INPUT TYPE=FILE NAME="Attach" SIZE="30" VALUE="<%$ARGS{'Attach'}%>"></td>
<tr><td>Create tickets in queue <%$Queue%> </td><td><INPUT TYPE=CHECKBOX NAME="Tickets" <% $Tickets ? "CHECKED='$Tickets'" : '' %></td>
<tr><td><%$Queue%> <br><& /Elements/EditCustomField, CustomField => $nsa, Default => $ARGS{$nsa->id ."-Values"} &></td>
<td>Network Scanned<br><& /Elements/EditCustomField, CustomField => $network, Default => $ARGS{$network->id ."-Values"} &></td>
</table>
<& /Elements/TitleBoxEnd &>
<& /Elements/Submit, Label => loc("Process")&>
</FORM>


<%INIT>
use XMLMAP;
use NSA;
use Data::Dumper;

my ($data, $filehandle, $uploadinfo, $nmap, $struct);
my ($non_db_exceptions, $db_exceptions);
my ($types, $counter);
my $bonus_info;

my $group = RT::Group->new($RT::SystemUser);
$group->LoadUserDefinedGroup('Security Consultants');
unless ( $group->HasMemberRecursively( $session{CurrentUser}->PrincipalObj )
      || $session{CurrentUser}->PrincipalObj->HasRight(Right => 'SuperUser', Object => $RT::System ) ) {
            $m->comp("/Elements/Error", Why => "Must be a member of: Security Consultants or be an RT SuperUser");
            $m->abort;
}

if ($ARGS{'Attach'}) {

    if ($filehandle = $m->cgi_object->upload('Attach') ) {

        $uploadinfo = $m->cgi_object->uploadInfo($filehandle);
        if ($uploadinfo->{'Content-Type'} ne 'text/xml') {
            $m->comp("/Elements/Error", Why => "$ARGS{Attach} does not appear to be a txt/xml file");
            $m->abort;
        }

        my $data;
        while (my $line = <$filehandle>) {
            $data .= $line;
        }
        $nmap = XMLMAP::new($data);
        $struct = XMLMAP::scan_struct($nmap);

        ($non_db_exceptions, $db_exceptions) = NSA::exceptions($struct);
        $types = RTx::AssetTracker::Types->new($RT::SystemUser);
        $types->UnLimit;

        $bonus_info = "\n\nScan Start: " . scalar(localtime $nmap->{start}) 
                    .   "\nScan   End: " . scalar(localtime $nmap->{runstats}{finished}{time}) 
                    . "\nDescription: $ARGS{Description}\nnmap options: " . $nmap->{args};

    }
    else {
            $m->comp("/Elements/Error", Why => "Uploaded file could not be read: $!");
            $m->abort;
    }
}

my $nsa    = RT::CustomField->new($session{CurrentUser});
my $risk   = RT::CustomField->new($session{CurrentUser});
my $status = RT::CustomField->new($session{CurrentUser});
my $guess  = RT::CustomField->new($session{CurrentUser});
my $ip     = RT::CustomField->new($session{CurrentUser});
my $ports  = RT::CustomField->new($session{CurrentUser});
my $network  = RT::CustomField->new($session{CurrentUser});
my ($cfrv, $cfmsg);

($cfrv, $cfmsg) = $nsa->   LoadByName(Name => $Queue, Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field $Queue: $cfmsg"); $m->abort; }
($cfrv, $cfmsg) = $risk->  LoadByName(Name => 'Risk', Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field Risk: $cfmsg"); $m->abort; }
($cfrv, $cfmsg) = $status->LoadByName(Name => 'Exception Status', Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field Exception Status: $cfmsg"); $m->abort; }
($cfrv, $cfmsg) = $guess-> LoadByName(Name => 'OS Guess', Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field OS Guess: $cfmsg"); $m->abort; }
($cfrv, $cfmsg) = $ip->    LoadByName(Name => 'NSA IP Address', Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field NSA IP Address: $cfmsg"); $m->abort; }
($cfrv, $cfmsg) = $ports-> LoadByName(Name => 'NSA Offending Ports', Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field NSA Offending Ports: $cfmsg"); $m->abort; }
($cfrv, $cfmsg) = $network-> LoadByName(Name => 'NSA Network Scanned', Queue => $Queue);
unless ($cfrv) { $m->comp('/Elements/Error', Why => "Custom field NSA Network Scanned: $cfmsg"); $m->abort; }

</%INIT>
<%ARGS>
$Queue       => 'NSA';
$Debug       => 0
$DebugNmap   => 0
$DebugStruct => 0
$DebugDBExcp => 1
$DebugNonDB  => 0
$Tickets     => undef
$TicketLimit => undef
</%ARGS>
<%CLEANUP>
if ($Debug) {
    $m->out( '<pre>', Dumper($nmap),   '</%pre>' ) if $DebugNmap;
    $m->out( '<pre>', Dumper($struct), '</%pre>' ) if $DebugStruct;
    $m->out( '<pre>', Dumper($db_exceptions), '</%pre>' ) if $DebugDBExcp;
    $m->out( '<pre>', Dumper($non_db_exceptions), '</%pre>' ) if $DebugNonDB;
}
</%CLEANUP>
